package com.ehotting.mqbd.core.manager;

import com.ehotting.eaf.core.StringHelper;
import com.ehotting.eaf.core.utils.AssertUtils;
import com.ehotting.mqbd.api.bean.MsgStateBean;
import com.ehotting.mqbd.api.enums.MsgStateEnum;
import com.ehotting.mqbd.core.service.msg.MsgStateService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
public class MsgStateManager {

    private static final Logger logger = LoggerFactory.getLogger(MsgStateManager.class);

    @Autowired
    private MsgStateService msgStateService;

    public void put(String msgId,String  agentId,String serial){
        msgStateService.put(msgId,agentId,serial);
    }


    public MsgStateBean getByMsgIdAndCirculate(String msgId){
        MsgStateBean msgState = msgStateService.getByMsgId(msgId);
        int getMsgStateTimes = 0;
        while (msgState==null && getMsgStateTimes<9){
            logger.error("Get msgState[getMsgStateTimes:{}] is null.",getMsgStateTimes);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            getMsgStateTimes ++;
            msgState = msgStateService.getByMsgId(msgId);
        }
        return msgState;
    }

    public MsgStateBean getByMsgId(String msgId){
        return msgStateService.getByMsgId(msgId);
    }

    public void deleteByMsgId(String msgId){
        msgStateService.deleteByMsgId(msgId);
    }

    public void setSolving(String msgId){
        MsgStateBean msgState =  msgStateService.getByMsgId(msgId);
        if(msgState!=null){
            msgState.setState(MsgStateEnum.SOLVING);
            msgStateService.put(msgState);
        }
    }

    public void deleteByAgentIdAndSolving(String agentId){
        if(StringHelper.isBlank(agentId)){
            logger.error("agentId is null.return.");
            return;
        }
        List<MsgStateBean> msgStateList = findByAgentIdAndSolving(agentId);
        for(MsgStateBean msgState : msgStateList){
            msgStateService.deleteByMsgId(msgState.getMsgId());
        }
    }

    public List<MsgStateBean> findAllByAgentIdAndNew(String agentId){
        AssertUtils.hasText(agentId,"agentId is null.");
        List<MsgStateBean> msgStateList = findByAgentId(agentId);
        if(msgStateList.size()>0){
            msgStateList = msgStateList.stream().sorted(Comparator.comparing(MsgStateBean::getDate).reversed()).collect(Collectors.toList());
        }
        return msgStateList;
    }


    public List<MsgStateBean> findByModule(String module){
        AssertUtils.hasText(module,"module is null.");
        List<MsgStateBean> msgStateList = msgStateService.findByModule(module);
        return msgStateList;
    }

    public List<MsgStateBean> findByAgentId(String agentId){
        AssertUtils.hasText(agentId,"agentId is null.");
        List<MsgStateBean> msgStateList =  msgStateService.findByAgentId(agentId);
        return msgStateList;
    }

    public List<MsgStateBean> findByAgentIdAndSolving(String agentId){
        AssertUtils.hasText(agentId,"agentId is null.");
        List<MsgStateBean> msgStateList =  msgStateService.findByAgentId(agentId);
        List<MsgStateBean> msgStateSolvingList = msgStateList.stream().filter(t->t.getState()==MsgStateEnum.SOLVING).collect(Collectors.toList());
        return msgStateSolvingList;
    }

    public MsgStateBean getByAgentIdAndSolving(String agentId){
        List<MsgStateBean> msgStateSolvingList = findByAgentIdAndSolving(agentId);
        MsgStateBean msgState = msgStateSolvingList.stream().findFirst().orElseGet(null);
        return msgState;
    }


    public List<MsgStateBean> findInQueueByModuleAndSorted(String module){
        AssertUtils.hasText(module,"module is null.");
        List<MsgStateBean> msgStateList = findByModule(module);
        msgStateList = msgStateList.stream().sorted(Comparator.comparing(MsgStateBean::getDate)).collect(Collectors.toList());
        return msgStateList;
    }

    public List<MsgStateBean> findInQueueByModuleAndInQueueAndSorted(String module){
        AssertUtils.hasText(module,"module is null.");
        List<MsgStateBean> msgStateList = findByModule(module);
        msgStateList = msgStateList.stream().filter(t->t.getState()==MsgStateEnum.QUEUE).sorted(Comparator.comparing(MsgStateBean::getDate)).collect(Collectors.toList());
        return msgStateList;
    }

    public boolean clearInvalidCancelAndQueueState(String module,MsgStateBean currentMsgState){
        logger.info("Start clearInvalidState");
        List<MsgStateBean> msgStateList = findByModule(module);
        msgStateList = msgStateList.stream().filter(t->t.getDate().before(currentMsgState.getDate())).collect(Collectors.toList());
        logger.info("Delete msgStateList.size():{}",msgStateList.size());
        for(MsgStateBean msgState : msgStateList){
            clearInvalidState(msgState);
        }
        logger.info("Finish clearInvalidState");
        return false;
    }

    private void clearInvalidState(MsgStateBean msgState){
        logger.info("Start clearInvalidState");
        logger.info("mqQueueIndex:{},agentId:{}",msgState.getAgentId());
        if((msgState.getState() == MsgStateEnum.CANCEL || msgState.getState()== MsgStateEnum.QUEUE)){
            logger.info("Delete msg[agentId:{},id:{}],",msgState.getAgentId(),msgState.getMsgId());
            msgStateService.deleteByMsgId(msgState.getMsgId());
        }
        logger.info("Finish clearInvalidState");
    }


    public List<MsgStateBean> findInQueueByModuleAndInQueueAndSorted(String module, Date date){
        AssertUtils.hasText(module,"module is null.");
        List<MsgStateBean> msgStateList = findByModule(module);
        msgStateList = msgStateList.stream().filter(t->
                (t.getState()== MsgStateEnum.QUEUE  && t.getDate().getTime()>=date.getTime()))
                .sorted(Comparator.comparing(MsgStateBean::getDate)).collect(Collectors.toList());
        return msgStateList;
    }


    public long getQueueIndexByAgentId(String module, String agentId){
        List<MsgStateBean> msgStateList = findInQueueByModuleAndInQueueAndSorted(module);
        int queueIndex = 0;
        for(int index=0;index<msgStateList.size();index++){
            MsgStateBean msgState = msgStateList.get(index);
            queueIndex = queueIndex+1;
            if(msgState.getMsgId().equals(agentId)){
                return queueIndex;
            }
        }
        return 0;
    }

    public long getQueueIndexByMsgId(String module, String msgId){
        List<MsgStateBean> msgStateList = findInQueueByModuleAndInQueueAndSorted(module);
        int queueIndex = 0;
        for(int index=0;index<msgStateList.size();index++){
            MsgStateBean msgState = msgStateList.get(index);
            queueIndex = queueIndex+1;
            if(msgState.getMsgId().equals(msgId)){
                return queueIndex;
            }
        }
        return 0;
    }


    public String getMsgIdByAgentIdAndInQueue(String agentId){

        List<MsgStateBean> msgStateList = findAllByAgentIdAndNew(agentId);
        if(msgStateList.size()==0){
            return null;
        }

        if(msgStateList.size()==1){
            return msgStateList.get(0).getMsgId();
        }

        MsgStateBean msgState = msgStateList.stream().filter(t->{return t.getState()==MsgStateEnum.QUEUE;})
                .sorted(Comparator.comparing(MsgStateBean::getDate).reversed())
                .findFirst()
                .orElse(null);

        return msgState==null?msgStateList.get(0).getMsgId():msgState.getMsgId();
    }

    public MsgStateBean getByAgentIdAndInLive(String agentId){
        List<MsgStateBean> msgStateList = findAllByAgentIdAndNew(agentId);
        if(msgStateList.size()==0){
            return null;
        }

        MsgStateBean msgState = msgStateList.stream().filter(t->{return t.getState()!=MsgStateEnum.CANCEL;})
                .sorted(Comparator.comparing(MsgStateBean::getDate).reversed())
                .findFirst()
                .orElse(null);

        return msgState;
    }


    public Integer cancel(String agentId){
        logger.info("Start cancel");
        logger.info("Task cancel by agentId[{}]",agentId);
        List<MsgStateBean> msgStateList = msgStateService.findByAgentId(agentId);
        logger.info("msgStateList.size():{}",msgStateList.size());
        msgStateList.stream().forEach(msgState->{
            msgState.setState(MsgStateEnum.CANCEL);
            msgStateService.put(msgState);
        });
        logger.info("Start cancel");
        return msgStateList.size();
    }


    public  boolean isSolving(String agentId){
        List<MsgStateBean> msgStateList = msgStateService.findByAgentId(agentId);
        for(MsgStateBean t : msgStateList){
            if(t.getState() == MsgStateEnum.SOLVING){
                return true;
            }
        }
        return false;
    }


    public  MsgStateBean isInQueue(String agentId){
        List<MsgStateBean> msgStateList = msgStateService.findByAgentId(agentId);
        for(MsgStateBean t : msgStateList){
            if(t.getState() == MsgStateEnum.QUEUE){
                return t;
            }
        }
        return null;
    }


    public static void main(String[] args) {
        Date date1 = new Date();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Date date2 = new Date();
        System.out.println(date1.getTime()<date2.getTime());

    }


}